package com.naza.rpc.client;

import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.listener.Event;
import com.alibaba.nacos.api.naming.listener.EventListener;
import com.alibaba.nacos.api.naming.listener.NamingEvent;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.naza.rpc.model.ServiceInstance;
import com.naza.rpc.discovery.DiscoveryListener;
import com.naza.rpc.util.PropertiesUtil;

import java.util.ArrayList;
import java.util.List;

/**
 * nacos client
 *
 * @author yl
 */
public class NacosClient {

    private static Object LOCK = new Object();

    private NamingService naming;

    private static NacosClient INSTANCE = null;

    private String nacosServer = PropertiesUtil.getINSTANCE().getValue("register.addr");

    public static NacosClient getINSTANCE(){
        synchronized (LOCK){
            if(null == INSTANCE){
                synchronized (LOCK){
                    if(null == INSTANCE){
                        INSTANCE = new NacosClient();
                    }
                }
            }
        }
        return INSTANCE;
    }

    public NacosClient(){
        init();
    }
    public void init(){
        try {
            naming = NamingFactory.createNamingService(nacosServer);
        }catch (Exception e){

        }
    }

    public void registerInstance(String serviceName,Instance instance) throws NacosException {
        naming.registerInstance(serviceName,instance);
    }

    public void deRegisterInstance(String serviceName,Instance instance) throws NacosException {
        naming.deregisterInstance(serviceName, instance);
    }

    public List<Instance> getAllInstance(String serviceName) throws NacosException {
        List<Instance>  instances = naming.selectInstances(serviceName,true);
        return instances;
    }

    public void monitor(String serviceName, DiscoveryListener listener) throws NacosException {
        naming.subscribe(serviceName, new EventListener() {
            @Override
            public void onEvent(Event event) {
                NamingEvent e = (NamingEvent)event;
                List<Instance> all = e.getInstances();
                List<ServiceInstance> serviceInstances = new ArrayList<>();
                for(Instance instance : all){
                    if(instance.isHealthy()){
                        serviceInstances.add(createServiceInstance(instance));
                    }
                }
                listener.instanceChanged(serviceInstances);
            }
        });
    }

    private ServiceInstance createServiceInstance(Instance instance){
        ServiceInstance serviceInstance = new ServiceInstance();
        serviceInstance.setServiceName(instance.getServiceName());
        serviceInstance.setPort(instance.getPort());
        serviceInstance.setIp(instance.getIp());
        serviceInstance.setId(instance.getInstanceId());
        serviceInstance.setApplicationName(instance.getClusterName());
        return serviceInstance;
    }
}
